package Twitter.Listener;

import java.io.IOException;

import java.io.PrintWriter;

import java.net.ServerSocket;
import java.net.Socket;

import java.util.HashMap;
import java.util.concurrent.ExecutorService;

import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.log4j.*;
import org.w3c.dom.Document;

import twitter.Database.TwitterMaintainer;

import twitter.RequestHandler.BackendHttpRequestHandler;
import twitter.RequestHandler.FrontendHttpRequestHandler;
import twitter.RequestHandler.HTTPRequestHandler;
import twitter.RequestHandler.NoticeResponseHandler;
import twitter.RequestHandler.PrimaryRequestHandler;
import twitter.RequestHandler.RequestHandlerAdapter;
import twitter.Server.ServerType;
import twitter.TwitterLibrary.Utility;
/******************************************************************
 * This class is listening for socket request
 * It could be shut down
 * when it receives a request,will generate a HTTPRequestHandler object and put it in the thread pool to execute for handling this request.
 * @author fang
 *
 */
public class RequestListener {
	protected ServerSocket serverSocket;	
	protected Socket clientSocket=null;
	protected PrintWriter out = null;
	private ExecutorService threadPool;
	private final ReentrantReadWriteLock rwl ;
	private RequestHandlerAdapter handlerAdapter;
	private HashMap<String, Document> versionCache ;
	private HashMap<String, Integer> tagCache ;
	private TwitterMaintainer twitterMaintainer;
	private boolean shutdown=false;
	private Utility utility;
	static Logger logger=Logger.getLogger(RequestListener.class);
	
	/***************************************
	 * Class constructor
	 * @param threadPool an object of ExecutorService.It could execute Runnable objects.
	 */
	public RequestListener(ReentrantReadWriteLock rwl,ExecutorService threadPool,Utility utility)
	{
		this.rwl=rwl;
		this.threadPool=threadPool;
		handlerAdapter=new RequestHandlerAdapter();
		this.versionCache= new HashMap<String, Document>();
		this.tagCache = new HashMap<String, Integer>();
		this.utility=utility;
		this.twitterMaintainer=new TwitterMaintainer(rwl,utility);
		BasicConfigurator.configure();
		
	}
	/**********************************************
	 * Setting the shutdown variable, if the shutdown variable is true, then the request listener will be shut down
	 */
	public void shutdown()
	{
		this.shutdown=true;
	}
	/**************************************************
	 * opens the server socket to the specific port
	 * @param port specify which port is listening now
	 */
	public void listenToSocket(int port)
	{
		
		try {
			serverSocket = new ServerSocket(port);
		} catch (IOException e) {
			//logger.error("Could not listen on port: " + port);
			e.printStackTrace();
			System.exit(1);
		}
		
	}
	/******************************************************************
	 * return the ServerSocket object for shut down control
	 * @return ServerSocket
	 */
	public ServerSocket getServerSocket()
	{
		return this.serverSocket;
	}

	
	/***********************************************************
	 * while the listerner is not shut down, catchRequest will listening to the request send to the serverSocket.
	 * when it receives one request,an object of RequestHandlerAdapter will generate HttpRequestHandler according to the 
	 * "end" parameter.If the end parameter is "connection", then it will generate one FrontendHttpRequestHandler to handle
	 * this request.If the end parameter is "end", then it will generate one BackendHttpRequestHandler to handle this request.
	 * After the right version of request handler is generated,the  ExecutorService will execute this handler.
	 * @param end specify which kind of HTTPRequestHandler it should use
	 */
	public void catchRequest()
	{
		while(!shutdown)
		{
			try {
				clientSocket = serverSocket.accept();
				//logger.info("processing one request .......");	
				//System.out.println("end string :"+end);
				HTTPRequestHandler handler=new HTTPRequestHandler(rwl,utility);
				handler.setTask(clientSocket);
				handler.setTwitterMaintainer(this.twitterMaintainer);
				threadPool.execute(handler);
				
				
			/************************************************************	
				
				if (handler instanceof FrontendHttpRequestHandler) {
					FrontendHttpRequestHandler frontendHandler = (FrontendHttpRequestHandler)handler;
					frontendHandler.setCache(versionCache, tagCache);
					frontendHandler.setTask(clientSocket);
					threadPool.execute(frontendHandler);
					}
				else if(handler instanceof BackendHttpRequestHandler)
				{
					BackendHttpRequestHandler backendHandler=(BackendHttpRequestHandler)handler;
					backendHandler.setTwitterMaintainer(twitterMaintainer);
					backendHandler.setTask(clientSocket);
					threadPool.execute(backendHandler);
				}
				else if(handler instanceof NoticeResponseHandler)
				{
					NoticeResponseHandler noticeResponseHandler=(NoticeResponseHandler)handler;
					noticeResponseHandler.setTask(clientSocket);
					threadPool.execute(noticeResponseHandler);
				}
				else if(handler instanceof PrimaryRequestHandler)
				{
					PrimaryRequestHandler backendHandler=(PrimaryRequestHandler)handler;
					backendHandler.setTwitterMaintainer(twitterMaintainer);
					backendHandler.setTask(clientSocket);
					threadPool.execute(backendHandler);
				}
				
****************************************************************/
			
			} catch (IOException e) {

			}
		
			
		}

	}
}
